#pragma once

namespace umtl
{
	//////////////////////////////////////////////////////////////////////////
	//

	template<typename DataType>
	lockfree_queue<DataType>::lockfree_queue()
		: iocp(CreateIoCompletionPort( INVALID_HANDLE_VALUE, NULL, 0, 1 ))
	{}

	//////////////////////////////////////////////////////////////////////////
	//

	template<typename DataType>
	lockfree_queue<DataType>::~lockfree_queue()
	{
		if( is_valid() )
		{
			PostQueuedCompletionStatus( iocp, 0, (ULONG_PTR)this, 0 );

			CloseHandle( iocp );
		}
	}

	//////////////////////////////////////////////////////////////////////////
	//

	template<typename DataType>
	bool lockfree_queue<DataType>::push( const DataType * data )
	{
		if( is_valid() )
		{
			InterlockedIncrement( &qeueSize );

			PostQueuedCompletionStatus( iocp, 0, (ULONG_PTR)data, 0 );

			return true;
		}

		return false;
	}

	//////////////////////////////////////////////////////////////////////////
	//

	template<typename DataType>
	bool lockfree_queue<DataType>::pop( DataType*& data )
	{
		if ( is_valid() == false )
		{
			return false;
		}

		DWORD transferredBytes = 0;
		ULONG_PTR completion_key;
		LPOVERLAPPED overlapped;

		if ( GetQueuedCompletionStatus( iocp, &transferredBytes, &completion_key, &overlapped, 0 ) == FALSE )
		{
			return false;
		}

		data = (DataType*)completion_key;

		InterlockedDecrement( &qeueSize );
		
		return true;
	}

	//////////////////////////////////////////////////////////////////////////
}